// ==UserScript==
// @name         BL Data Query Helper
// @namespace    http://tampermonkey.net/
// @version      0.6
// @include      http*://*.blushmark.com/*
// @include      http://localhost:3012/*
// @include      http://localhost:3002/*
// @description  Hover on the product on the list page to display the CTR, CR and sales data of the product.
// @author       BL
// @match        http://*/*
// @grant        GM_addStyle
// @updateURL    https://gitee.com/zhangqi_0428/data_tracker/blob/master/src/BLDataQueryHelper.js

// ==/UserScript==

const willRequests = []
const onGoingRequests = []
const maxConcurrency = 5

const beginRequest = (func) => {
    if (func) {
        if (onGoingRequests.length < maxConcurrency) {
            onGoingRequests.push(func)
            func()
        } else {
            willRequests.push(func)
        }
    }
}
const stopRequest = () => {
    onGoingRequests.pop()
    if (willRequests.length > 0) {
        const func = willRequests.shift()
        onGoingRequests.push(func)
        func()
    }
}

// 强依赖网站的参数
// 1.cookie中的 hasLogin, login_token
// 2.商品div中的class goods-item
// 3.商品div中的class goods-item 的上级div 要有 data-goods-id data-style-id参数

const getQueryStringValue = (key) => {
    return decodeURIComponent(window.location.search.replace(new RegExp('^(?:.*[&\\?]' + encodeURIComponent(key).replace(/[\.\+\*]/g, '\\$&') + '(?:\\=([^&]*))?)?.*$', 'i'), '$1'))
}

const getHost = () => {
    const hostName = window.location.hostname
    let host = 'https://www.blushmark.com/prod'
    if (hostName.startsWith('ft') || hostName.startsWith('ft-x')) {
        host = `https://${hostName}/test`
    } else if (hostName.startsWith('p')) {
        host = `https://${hostName}/pre`
    }
    return host
}

const getUrl = (url, params = {}) => {
    let host = getHost()
    console.log('url====>', url)
    console.log('host====>', host)
    console.log('params====>', params)
    const keys = Object.keys(params)
    keys && keys.map((key) => {
        url = url + (url.includes('?') ? '&' : '?') + `${key}=${params[key]}`
    })
    return host + url
}

const GET = (path, params, callback) => {
    beginRequest(() => {
        const xhr = new XMLHttpRequest()
        const url = getUrl(path, params)
        console.log('url====>', url)
        xhr.open('GET', url, true)
        xhr.onreadystatechange = function() {
            if (xhr.readyState == 4) {
                const info = JSON.parse(xhr.responseText)
                if (info && info.code == 0) {
                    callback(info.data)
                } else {
                    callback(undefined)
                }
                stopRequest()
            }
        }
        xhr.send()
    })
}

const fetchData = (goodsId, styleId, callback) => {
    const isAllListPage = window.location.pathname.startsWith('/categories/0_0/')
    const isClearance = window.location.pathname.startsWith('/clearance')
    const isSortByNew = window.location.search.includes('sort_by=new')
    const params = {
        styleId: styleId,
        callback: goodsId,
        type: (isAllListPage ? getQueryStringValue('type') : ''),
        pageType: (isClearance ? 'clearance' : isSortByNew ? 'just_in' : 'normal')
    }
    GET('/1.0/plugin/ctr-detail', params, callback)
}

const indexGetData = (ec, el, list_page_path, callback) => {
    const params = {
        path: list_page_path,
        ec: ec,
        el: el
    }
    GET('/1.0/home/plugin-ctr', params, callback)
}

const productGetData = (goods_id, style_id, size_id, callback) => {
    const params = {
        goods_id: goods_id,
        style_id: style_id,
        size_id: size_id
    }
    GET('/1.0/home/getStockTransit', params, callback)
}

const HTTP = {
    fetchData,
    indexGetData,
    productGetData
}

const elementIdentifier = 'chrome-extension-info'
const elementProductIdentifer = 'chrome-extension-info-product'
const MOUSE_VISITED_CLASS_NAME = 'goods-item'
const MOUSE_VISITED_CLASS_NAME_INDEX = 'ctr-index'
const MOUSE_VISITED_CLASS_NAME_PRODUCT = 'ctr-product'

// 强依赖网站的参数
// 1.cookie中的 hasLogin, login_token
// 2.商品div中的class goods-item
// 3.商品div中的class goods-item 的上级div 要有 data-goods-id data-style-id参数
const createRowElement = (dataElement, text) => {
    const container = document.createElement('span')
    container.className = 'extension-container'
    const textElement = document.createTextNode(text)
    container.appendChild(textElement)
    dataElement.appendChild(container)
    return container
}

/**
 * 获取containerElement
 * @param element
 */
const getContainerElement = (element) => {
    let containerElement = null
    if (element && element.className.indexOf(MOUSE_VISITED_CLASS_NAME) >= 0) {
        // 商品在此获取数据
        const findGoodsImageElementFunc = (elements) => {
            elements && Array.from(elements).some(e => {
                if (e && e.classList && e.classList.value.indexOf('goods-item-pic') >= 0) {
                    containerElement = e
                    return true
                }
                findGoodsImageElementFunc(e.children)
            })
        }
        findGoodsImageElementFunc(element.children)
    } else {
        // 首页和详情页在此获取数据
        containerElement = element
    }
    return containerElement
}

const showListCover = (containerElement) => {
    if (!containerElement || !containerElement.parentElement) {
        return
    }
    // 商品获取方式
    const goodsId = containerElement.parentElement.getAttribute('data-goods-id')
    const styleId = containerElement.parentElement.getAttribute('data-style-id')
    const pageType = containerElement.parentElement.getAttribute('page-type')
    // 参数不合法 退出
    if (!goodsId || !styleId || !pageType) return

    const children = Array.from(containerElement.children)
    let isExist = false
    children && children.map(e => {
        if (e.id === elementIdentifier) {
            if (e.dataId === goodsId + '' + styleId) {
                isExist = true
            } else {
                // 存在一个其他商品的数据 移除
                e.parentNode.removeChild(e)
            }
        }
    })
    // 已经存在了 不再次展示
    if (isExist) return
    const dataElement = document.createElement('div')
    dataElement.id = elementIdentifier
    dataElement.dataId = goodsId + '' + styleId
    dataElement.style.zIndex = 100

    const ctrElement = createRowElement(dataElement, 'CTR: -%')
    let justInElement
    if (pageType == 'just_in') {
        justInElement = createRowElement(dataElement, 'BST_CTR: -')
    }
    const crElement = createRowElement(dataElement, 'CR: -%')
    const ctrCrElement = createRowElement(dataElement, pageType == 'just_in' ? 'BST_CTR*CR: -' : 'CTR*CR: -')
    const saleElement = createRowElement(dataElement, 'SAL: -')
    const averageElement = createRowElement(dataElement, 'AVE: -')
    const clickElement = createRowElement(dataElement, 'CLI: -')
    const impressionElement = createRowElement(dataElement, 'IMP: -')
    const userElement = createRowElement(dataElement, 'DET: -')
    const ostElement = createRowElement(dataElement, 'OST: -')
    const abElement = createRowElement(dataElement, '')
    abElement.style.display = 'none'
    containerElement && containerElement.appendChild(dataElement)
    HTTP.fetchData(goodsId, styleId, (data) => {
        if (data) {
            const { cr, ctr, sales, viewCount, clickCount, showNumber, onSaleTime, ab_test, ctrCr, goodsSales, bestSellerCtr, averageDailySales } = data
            ctrElement.textContent = 'CTR: ' + ctr
            crElement.textContent = 'CR: ' + cr
            saleElement.textContent = 'SAL: ' + sales + '(' + goodsSales + ')'
            clickElement.textContent = 'CLI: ' + clickCount
            impressionElement.textContent = 'IMP: ' + viewCount
            userElement.textContent = 'DET: ' + showNumber
            ostElement.textContent = 'OST: ' + onSaleTime
            ctrCrElement.textContent = (pageType == 'just_in' ? 'BST_CTR*CR:' : 'CTR*CR: ') + ctrCr
            averageElement.textContent = 'AVE: ' + averageDailySales
            if (ab_test) {
                abElement.textContent = 'A/B Test'
                abElement.style.display = 'block'
            }

            if (pageType == 'just_in') {
                if (bestSellerCtr == undefined) {
                    justInElement.parentElement.removeChild(justInElement)
                } else { justInElement.textContent = 'BST_CTR:' + bestSellerCtr }
            }
        }
    })
}

const showHomeCover = (element, containerElement) => {
    if (!element || !containerElement) {
        return
    }
    const children = Array.from(containerElement.children)
    let isExist = false
    children && children.map(e => {
        if (e.id === elementIdentifier) {
            isExist = true
        }
    })
    // 已经存在了 不再次展示
    if (isExist) return
    const ec = element.getAttribute('ec')
    const el = element.getAttribute('el')
    const list_page_path = element.getAttribute('list_page_path')
    // 参数不合法
    if (!ec || !el || !list_page_path) return

    const dataElement = document.createElement('div')
    dataElement.id = elementIdentifier
    dataElement.style.zIndex = 100

    const ctrElement = createRowElement(dataElement, 'CTR: -%')
    const clickElement = createRowElement(dataElement, 'Click: -')
    const viewElement = createRowElement(dataElement, 'Impression: -')
    HTTP.indexGetData(ec, el, list_page_path, (data) => {
        if (data) {
            const { ctr, click_count, view_count } = data
            ctrElement.textContent = 'CTR: ' + (ctr || '0%')
            clickElement.textContent = 'Click: ' + (click_count || 0)
            viewElement.textContent = 'Impression: ' + (view_count || 0)
        }
    })
    containerElement && containerElement.appendChild(dataElement)
}

const showDetailCover = (element, containerElement) => {
    if (!element || !containerElement) {
        return
    }
    const children = Array.from(containerElement.children)
    let isExist = false
    children && children.map(e => {
        if (e.id === elementProductIdentifer && e.style_id === element.getAttribute('selectedColorId')) {
            isExist = true
        }

        if (e.style_id !== element.getAttribute('selectedColorId')) {
            if (e.id === elementProductIdentifer) {
                e && e.parentNode.removeChild(e)
            }
        }
    })

    // 已经存在了 不再次展示
    if (isExist) return

    const goods_id = element.getAttribute('selectedGoodsId')
    const style_id = element.getAttribute('selectedColorId')
    const size_id = element.getAttribute('selectedSizeId')
    // 参数不合法
    if (!goods_id || !style_id || !size_id) return

    const dataElement = document.createElement('div')
    dataElement.id = elementProductIdentifer
    dataElement.style.zIndex = 1
    const showElement = createRowElement(dataElement, '-')
    dataElement.style_id = style_id
    const showElement2 = createRowElement(dataElement, '')
    HTTP.productGetData(goods_id, style_id, size_id, (data) => {
        if (data) {
            if (data.has_virtual) {
                const result = data.stockTransit && data.stockTransit.split('[')
                showElement.innerHTML = result[0] + '<br>[' + result[1]
            } else {
                showElement.innerHTML = data.stockTransit
            }
            if (data.has_virtual) { showElement2.textContent = 'Virtual' }
        }
    })
    containerElement && containerElement.appendChild(dataElement)
}

const isLogin = () => {
    return document.cookie && document.cookie.includes('hasLogin=1;')
}

const beginTimer = () => {
    console.log('开始脚本====>')
    // 每秒检查 一次
    setInterval(() => {
        // 遍历所有节点，取所有的商品模块
        // 判断该商品模块是否已经有
        // 如果没有，则加入模块，并请求接口
        // 如果已经有了，则啥都不做
        if (isLogin()) {
            // 如果是首页商品不展示内容
            // 列表页面
            const elements = Array.from(document.getElementsByClassName(MOUSE_VISITED_CLASS_NAME))
            if (window.location.pathname != '/' && elements && elements.length > 0) {
                elements.map((element) => {
                    let containerElement = getContainerElement(element)
                    showListCover(containerElement)
                })
            }
            // 首页
            const indexElements = Array.from(document.getElementsByClassName(MOUSE_VISITED_CLASS_NAME_INDEX))
            if (indexElements && indexElements.length > 0) {
                indexElements.map((element) => {
                    showHomeCover(element, element)
                })
            }
            // 详情页面
            const productElements = Array.from(document.getElementsByClassName(MOUSE_VISITED_CLASS_NAME_PRODUCT))
            if (productElements && productElements.length > 0) {
                productElements.map((element) => {
                    showDetailCover(element, element)
                })
            }
        }
    }, 1000)
}

const main = () => {
    beginTimer()
}

main()


GM_addStyle(`
#chrome-extension-info-product{
    position: absolute;
    top: 0;
    bottom:0;
    right: 0;
    left: 0;
    height: 35px;
}

#chrome-extension-info {
    position: absolute;
    bottom: 0;
    right: 0;
    left: 0;
    min-height: 60px;
    background: rgba(255, 255, 255, 0.8);
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    padding: 10px 0px;
    min-width: 150px;
}

#chrome-extension-info .extension-container {
    min-width: calc((100% - 84px)/ 2);
    display: inline-block;
    font-size: 12px;
    color: #333;
    font-family: 'Montserrat SemiBold';
    line-height: 13px;
    text-align: left;
    margin-left: 20px;
    padding-left: 8px;
    position: relative;
    margin-bottom: 5px;
}

#chrome-extension-info .extension-container::before {
    content: '';
    position: absolute;
    left: -8px;
    top: 0px;
    width: 10px;
    height: 10px;
    border: 1px solid #FFFFFF;
    background: #F2CE99;
    border-radius: 10px;
    line-height: 13px;
}

#chrome-extension-info .extension-container:nth-child(2n+1)::before {
    background: #F2CE99;
    border: 1px solid #FFFFFF;
}

#chrome-extension-info .extension-container:nth-child(2n)::before {
    background: #93D1F5;
    border: 1px solid #FFFFFF;
}

#chrome-extension-info-product .extension-container{
    position: absolute;
    left: 0;
    width: 100%;
    height: 15px;
    text-align: center;
}

#chrome-extension-info-product .extension-container:nth-child(1){
    bottom:-15px;
    color: red;
}

#chrome-extension-info-product .extension-container:nth-child(2){
    top:-15px;
    color: blue;
}
`)
